package vq.codec.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * This class contains useful methods in order to perform generic tasks. 
 * 
 * @author Bruno Cartaxo
 * 
 * @since SEP 2009
 */
public class Util {

	/**
	 * This method aims to search given value in the given map, returning true 
	 * if it is present and false otherwise.
	 * 
	 * @param <K> The map key type.
	 * @param <V> The map value type.
	 * @param value The value that will be searched in the given map.
	 * @param map The map that serves as source of the search.
	 * @return True if the map contains the given value and false otherwise.
	 * 
	 * @author Bruno Cartaxo
	 */
	public static <K, V> boolean containsValue(V value, Map<K, V> map) {
		for (K key : map.keySet()) {
			V currentValue = map.get(key);
			if (currentValue.equals(value)) {
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * This method aims to search a key associated with the given value in the
	 * given map, returning the key if it founded and null otherwise.
	 * 
	 * @param <K> The map key type.
	 * @param <V> The map value type.
	 * @param value The value that will be used to search the key.
	 * @param map The map that serves as source of the search.
	 * @return The key associated with the given value if it founded, null otherwise.
	 * 
	 * @author Bruno Cartaxo
	 */
	public static <K, V> K getKey(V value, Map<K, V> map) {
		for (K key : map.keySet()) {
			V currentValue = map.get(key);
			if (currentValue.equals(value)) {
				return key;
			}
		}
		
		return null;
	}
	
	/**
	 * This method aims to return the maximum key of the given map.
	 *  
	 * @param <K> The map key type.
	 * @param <V> The map value type.
	 * @param map The map that serves as source of the search.
	 * @return The maximum key of the given map.
	 * 
	 * @author Bruno Cartaxo
	 */
	public static <K extends Comparable<K>, V> K maxKey(Map<K, V> map) {
		List<K> list = new ArrayList<K>();
		
		for (K item : map.keySet()) {
			list.add(item);
		}
		
		return Collections.max(list);
	}
	
	public static List<Integer> doubleToIntegerList(List<Double> list) {
		List<Integer> toReturn = new ArrayList<Integer>();
		
		for (int i = 0; i < list.size(); i++) {
			Double currentDouble = list.get(i);
			toReturn.add((int)Math.round(currentDouble));
		}
		
		return toReturn;
	}
	
	/**
	 * This method aims to return true if the given object is null and false otherwise.
	 * 
	 * @param object The object that will be check by nullability.
	 * @return True if the given object is null and false otherwise.
	 * 
	 * @author Bruno Cartaxo
	 */
	public static boolean isNull(Object object) {
		return object == null;
	}
	
	/**
	 * This method aims to return true if the given string is null or is an
	 * empty string, false otherwise.
	 * 
	 * @param string The string that will be check by nullability and emptyness.
	 * @return True if the given string is null or empty, false otherwise.
	 * 
	 * @author Bruno Cartaxo
	 */
	public static boolean isNullOrEmpty(String string) {
		return isNull(string) || string.length() == 0; 
	}
	
	/**
	 * This method aims to return true if the given map is null or do no contain
	 * any element, false otherwise.
	 * 
	 * @param <K> The map key type.
	 * @param <V> The map value type.
	 * @param map The map that will be checked by nullability and emptyness.
	 * @return True if the given map is null or do no contain any element, false 
	 *         otherwise.
	 * 
	 * @author Bruno Cartaxo
	 */
	public static <K, V> boolean isNullOrEmpty(Map<K, V> map) {
		return isNull(map) || map.size() == 0; 
	}
	
}
